<?php if (!defined('BASEPATH'))exit('No direct script access allowed');

include_once 'ExceptionDAO.php';
include_once 'util/MapError.php';
include_once 'TOGrupo.php';

/**
 * DAO para operações de banco para grupo
 * 
 * @author Douglas Rafael
 */
class DAOGrupo extends CI_Model {
    
    /**
     * Lista todas os grupos
     * 
     * @param int    $init          Posição inicial do cursor
     * @param int    $quant         Total de registros
     * @param string $orderby       Nome da coluna a ser ordenada
     * @param string $direction     Direção: ASC ou DESC
     * @param bool   $limit         Ativa ou desativa o limit na consulta
     * @return array TOGrupo        Array de objetos
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function select_all_groups($init, $quant, $orderby = NULL, $direction = NULL, $limit = TRUE) {
        try {
            $orderby != NULL && $direction != NULL ? $this->db->order_by($orderby, $direction) : $this->db->order_by('id', 'ASC');
            $result = $limit ? $this->db->get('grupo', $quant, $init) :  $this->db->get('grupo');

            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar listar os grupos.');
            } else {
                $grupos = array();
                $this->load->model('DAOAcao');
                foreach ($result->result() as $value) {
                    $grupo = new TOGrupo();
                    $grupo->id = $value->id;
                    $grupo->nome = $value->nome;
                    $grupo->descricao =  $value->descricao;
                    $grupo->status = $value->status;
                    
                    // Pega as ações pertencentes ao grupo
                    $grupo->acoes = $this->DAOAcao->get_action_group($grupo->id);
                    
                    array_push($grupos, $grupo);
                }
                return $grupos;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }

    /**
     * Retorna o Total geral grupos cadastrados.
     * 
     * @return int Total de resgistros
     */
    public function amount_all_groups() {
        return $this->db->count_all_results('grupo');
    }
    
     /**
     * Seleciona um grupo de acordo com seu id
     * 
     * @param  TOGrupo $grupo   Obejto grupo contendo o id
     * @return TOGrupo          Retorna Obejeto grupo
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function get_group(TOGrupo $grupo) {
        try {
            $result = $this->db->query('
                                        SELECT 
                                            grupo.nome,
                                            grupo.id,
                                            grupo.descricao,
                                            grupo.status,
                                            IF(
                                              acao_has_grupo.acao_id = 0,
                                              TRUE,
                                              FALSE
                                            ) AS super_admin 
                                          FROM
                                            grupo 
                                            JOIN acao_has_grupo 
                                              ON acao_has_grupo.grupo_id = grupo.id 
                                          WHERE grupo.id = ' . $grupo->id .
                                          ' GROUP BY grupo.id');
            
            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar selecionar grupo.');
            } else {
                $value = $result->row();
                
                $this->load->model('DAOAcao');
                $grupo = new TOGrupo();
                $grupo->id = $value->id;
                $grupo->nome = $value->nome;
                $grupo->descricao = $value->descricao;
                $grupo->status = $value->status;
                $grupo->super_admin = $value->super_admin;
                
                // Pega as ações pertencentes ao grupo
                $grupo->acoes = $this->DAOAcao->get_action_group($grupo->id);
                
                return $grupo;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Insere no banco de dados o grupo e suas açoes
     * 
     * @param  TOGrupo $grupo   Obejeto grupo contendo dados para inserir
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function insert_group(TOGrupo $grupo) {
        try {
            $this->db->trans_start();
            
            $result = $this->db->insert('grupo', $grupo);

            if (!$result) {
                //Traduz o tipo de erro de acordo com $num
                $erro = new MapError();
                throw new Exception($erro->getError($this->db->_error_number(), $this->db->_error_message(), $grupo->nome));
            } else {
                $grupo->id = $this->db->insert_id(); // Pegendo o id do item inserido

                //Insere as ações do grupo
                $this->load->model('DAOAcao');
                $this->DAOAcao->insert_action_group($grupo);
                
                $this->db->trans_complete();

                if ($this->db->trans_status() === FALSE) {
                    throw new Exception('Ocorreu um erro de banco de dados ao tentar inserir o grupo.');
                }
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    /**
     * Atualiza dados do grupo
     * 
     * @param TOGrupo $grupo    Obejto grupo contendo os dados para atualizar
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function update_group(TOGrupo $grupo) {
        try {
            $this->db->trans_start();
            
            $this->db->where('id', $grupo->id);
            $result = $this->db->update('grupo', $grupo);

            if (!$result) {
                //Traduz o tipo de erro de acordo com $num
                $erro = new MapError();
                throw new Exception($erro->getError($this->db->_error_number(), $this->db->_error_message(), $grupo->nome));
            } else {
                //Insere as ações do grupo
                $this->load->model('DAOAcao');
                $this->DAOAcao->update_action_group($grupo);

                $this->db->trans_complete();

                if ($this->db->trans_status() === FALSE) {
                    throw new Exception('Ocorreu um erro de banco de dados ao tentar atualizar o grupo: <span class="bold">' . $grupo->nome . '</span>');
                }
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Efeutua busca por grupos
     * 
     * @param int    $init          Posição inicial do cursor
     * @param int    $quant         Total de registros
     * @param string $orderby       Nome da coluna a ser ordenada
     * @param string $direction     Direção: ASC ou DESC
     * @param bool   $limit         Ativa ou desativa o limit na consulta
     * @return array TOGrupo        Array de objetos
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function search_group($init, $quant, $term = NULL, $orderby = NULL, $direction = NULL) {
        try {
            $this->db->select('grupo.id AS id, grupo.nome AS nome, grupo.descricao AS descricao, grupo.status AS status');
            $this->db->like('grupo.id', $term);
            $this->db->or_like('grupo.nome', $term);
            $this->db->or_like('acao.nome', $term);
            $this->db->join('acao_has_grupo', 'acao_has_grupo.grupo_id = grupo.id');
            $this->db->join('acao', 'acao.id = acao_has_grupo.acao_id');
            $this->db->group_by('grupo.id');
            $orderby != NULL && $direction != NULL ? $this->db->order_by($orderby, $direction) : $this->db->order_by('grupo.id', 'ASC');
           
            $result = $this->db->get('grupo', $quant, $init);

            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar efetuar busca por grupos.');
            } else {
                $grupos = array();
                $this->load->model('DAOAcao');
                foreach ($result->result() as $value) {
                    $grupo = new TOGrupo();
                    $grupo->id = $value->id;
                    $grupo->nome = $value->nome;
                    $grupo->descricao =  $value->descricao;
                    $grupo->status = $value->status;
                    
                    // Pega as ações pertencentes ao grupo
                    $grupo->acoes = $this->DAOAcao->get_action_group($grupo->id);
                    
                    array_push($grupos, $grupo);
                }
                return $grupos;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    /**
     * Retorna a quantidade de registros da busca
     * 
     * @param string $term
     * @return int
     */
    public function amount_search_group($term) {
        $this->db->select('grupo.id AS id, grupo.nome AS nome, grupo.descricao AS descricao, grupo.status AS status');
        $this->db->like('grupo.id', $term);
        $this->db->or_like('grupo.nome', $term);
        $this->db->or_like('acao.nome', $term);
        $this->db->join('acao_has_grupo', 'acao_has_grupo.grupo_id = grupo.id');
        $this->db->join('acao', 'acao.id = acao_has_grupo.acao_id');
        $this->db->group_by('grupo.id');
        $result = $this->db->get('grupo');

        return count($result->result());
    }
    
    
    /**
     * Exclui do banco o grupo com suas respectivas acoes
     * 
     * @param TOGrupo $grupo    Obejto grupo contendo os ids para ser deletado
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function delete_group(TOGrupo $grupo) {
        try {
            $this->db->where_in('id', $grupo->id);
            $result = $this->db->delete('grupo');

            if (!$result) {
                //Traduz o tipo de erro de acordo com $num
                $erro = new MapError();
                throw new Exception($erro->getError($this->db->_error_number(), $this->db->_error_message(), $grupo->nome));
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
        
    /**
     * Seleciona os grupos e suas respectiva açõs do usuário de acordo com seu id
     * 
     * @param  $codigo_user     Código (id) do usuário
     * @return TOGrupo          Retorna array Obejeto grupo
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function get_groups_user($codigo_user) {
        try {
            $this->db->select('grupo.id, grupo.nome, grupo.descricao, grupo.status');
            $this->db->join('grupo', 'grupo.id = grupo_has_usuario.grupo_id');
            $this->db->join('usuario', 'usuario.id = grupo_has_usuario.usuario_id');
            $this->db->where('grupo_has_usuario.usuario_id', $codigo_user);
            $result = $this->db->get('grupo_has_usuario');
            
            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar listar os grupos do usuário.');
            } else {
                $grupos = array();
                $this->load->model('DAOAcao');
                foreach ($result->result() as $value) {
                    $grupo = new TOGrupo();
                    $grupo->id = $value->id;
                    $grupo->nome = $value->nome;
                    $grupo->descricao =  $value->descricao;
                    $grupo->status = $value->status;
                    
                    // Pega as ações pertencentes ao grupo
                    $grupo->acoes = $this->DAOAcao->get_action_group($grupo->id);
                    
                    array_push($grupos, $grupo);
                }

                return $grupos;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Insere os grupos do usuário
     * 
     * @param  TOUsuario $usuario   Obejto usuário contendo array com os grupos
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function insert_group_user(TOUsuario $usuario) {
        try {
            $grupos = array();
            foreach ($usuario->grupos as $value) {
                $data['usuario_id'] = $usuario->id;
                $data['grupo_id'] = $value->id;
                array_push($grupos, $data);
            }
            $result = $this->db->insert_batch('grupo_has_usuario', $grupos);

            $this->db->trans_complete();
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar inserir grupos do usuário.');
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Atualiza os grupos do usuário
     * - 1° Os grupos desse usuário já cadastradas são apagadas, e depois inseridas as novas
     */
    public function update_group_user(TOUsuario $usuario) {
        $this->delete_group_user($usuario->id) ? $this->insert_group_user($usuario) : '';
    }

    /**
     * Remove os grupos do usuário de acordo com seu id
     * 
     * @param  $codigo_user Código do usuário
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function delete_group_user($codigo_user) {
        try {
            $this->db->where('usuario_id', $codigo_user);
            $result = $this->db->delete('grupo_has_usuario');

            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar remover grupos do usuário.');
            } else {
                return TRUE;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
}